﻿using System.Web;
using WikiMaml.Renderers;
using WikiPlex;
using Xunit;
using Xunit.Extensions;

namespace WikiMaml.Facts.Renderers
{
    public class SourceCodeRendererFacts
    {
        public class CanExpand
        {
            [Theory]
            [InlineData(ScopeName.SingleLineCode)]
            [InlineData(ScopeName.MultiLineCode)]
            [InlineData(ScopeName.ColorCodeAshx)]
            [InlineData(ScopeName.ColorCodeAspxCs)]
            [InlineData(ScopeName.ColorCodeAspxVb)]
            [InlineData(ScopeName.ColorCodeCpp)]
            [InlineData(ScopeName.ColorCodeCSharp)]
            [InlineData(ScopeName.ColorCodeHtml)]
            [InlineData(ScopeName.ColorCodeJavaScript)]
            [InlineData(ScopeName.ColorCodeSql)]
            [InlineData(ScopeName.ColorCodeVbDotNet)]
            [InlineData(ScopeName.ColorCodeXml)]
            [InlineData(ScopeName.ColorCodePhp)]
            [InlineData(ScopeName.ColorCodeCss)]
            [InlineData(ScopeName.ColorCodeJava)]
            [InlineData(ScopeName.ColorCodePowerShell)]
            public void Should_be_able_to_resolve_scope_name(string scopeName)
            {
                var renderer = new SourceCodeRenderer();

                bool result = renderer.CanExpand(scopeName);

                Assert.True(result);
            }
        }

        public class Expand
        {
            [Fact]
            public void Should_resolve_the_single_line_code_scope_correctly()
            {
                var renderer = new SourceCodeRenderer();

                string result = renderer.Expand(ScopeName.SingleLineCode, "public class { }", x => x, x => x);

                Assert.Equal("<codeInline>public class { }</codeInline>", result);
            }

            [Fact]
            public void Should_resolve_the_single_line_code_scope_correctly_and_html_encode_the_content()
            {
                var renderer = new SourceCodeRenderer();

                string result = renderer.Expand(ScopeName.SingleLineCode, "&public class { }", HttpUtility.HtmlEncode, x => x);

                Assert.Equal("<codeInline>&amp;public class { }</codeInline>", result);
            }

            [Fact]
            public void Should_resolve_the_multi_line_code_scope_correctly()
            {
                var renderer = new SourceCodeRenderer();

                string result = renderer.Expand(ScopeName.MultiLineCode, "public class { }", x => x, x => x);

                Assert.Equal("<code language=\"none\">public class { }</code>", result);
            }

            [Fact]
            public void Should_resolve_the_multi_line_code_scope_correctly_and_html_encode_the_content()
            {
                var renderer = new SourceCodeRenderer();

                string result = renderer.Expand(ScopeName.MultiLineCode, "public &class { }", HttpUtility.HtmlEncode, x => x);

                Assert.Equal("<code language=\"none\">public &amp;class { }</code>", result);
            }

            [Fact]
            public void Should_remove_the_new_line_at_the_end_of_a_multi_line_code()
            {
                var renderer = new SourceCodeRenderer();

                string result = renderer.Expand(ScopeName.MultiLineCode, "public class { }\r\n", x => x, x => x);

                Assert.Equal("<code language=\"none\">public class { }</code>", result);
            }

            [Theory]
            [InlineData("html", ScopeName.ColorCodeAshx)]
            [InlineData("html", ScopeName.ColorCodeAspxCs)]
            [InlineData("html", ScopeName.ColorCodeAspxVb)]
            [InlineData("cpp", ScopeName.ColorCodeCpp)]
            [InlineData("cs", ScopeName.ColorCodeCSharp)]
            [InlineData("html", ScopeName.ColorCodeHtml)]
            [InlineData("js", ScopeName.ColorCodeJavaScript)]
            [InlineData("sql", ScopeName.ColorCodeSql)]
            [InlineData("vbnet", ScopeName.ColorCodeVbDotNet)]
            [InlineData("xml", ScopeName.ColorCodeXml)]
            [InlineData("none", ScopeName.ColorCodePhp)]
            [InlineData("none", ScopeName.ColorCodeCss)]
            [InlineData("none", ScopeName.ColorCodeJava)]
            [InlineData("powershell", ScopeName.ColorCodePowerShell)]
            public void Should_resolve_the_color_code_scope_correctly(string languageId, string scopeName)
            {
                var renderer = new SourceCodeRenderer();
                
                string result = renderer.Expand(scopeName, "foo", x => x, x => x);

                Assert.Equal("<code language=\"" + languageId + "\">foo</code>", result);
            }

            [Theory]
            [InlineData("html", ScopeName.ColorCodeAshx)]
            [InlineData("html", ScopeName.ColorCodeAspxCs)]
            [InlineData("html", ScopeName.ColorCodeAspxVb)]
            [InlineData("cpp", ScopeName.ColorCodeCpp)]
            [InlineData("cs", ScopeName.ColorCodeCSharp)]
            [InlineData("html", ScopeName.ColorCodeHtml)]
            [InlineData("js", ScopeName.ColorCodeJavaScript)]
            [InlineData("sql", ScopeName.ColorCodeSql)]
            [InlineData("vbnet", ScopeName.ColorCodeVbDotNet)]
            [InlineData("xml", ScopeName.ColorCodeXml)]
            [InlineData("none", ScopeName.ColorCodePhp)]
            [InlineData("none", ScopeName.ColorCodeCss)]
            [InlineData("none", ScopeName.ColorCodeJava)]
            [InlineData("powershell", ScopeName.ColorCodePowerShell)]
            public void Should_resolve_the_color_code_scope_correctly_and_html_encode(string languageId, string scopeName)
            {
                var renderer = new SourceCodeRenderer();

                string result = renderer.Expand(scopeName, "foo", x => "bar", x => x);

                Assert.Equal("<code language=\"" + languageId + "\">bar</code>", result);
            }

            [Fact]
            public void Should_return_content_for_invalid_scope_name()
            {
                var renderer = new SourceCodeRenderer();

                string result = renderer.Expand("foo", "in", x => x, x => x);

                Assert.Equal("in", result);
            }
        }
    }
}
